package BLC

import (
	"bytes"
	"crypto/ecdsa"
	"crypto/elliptic"
	"crypto/rand"
	"crypto/sha256"
	"fmt"
	"golang.org/x/crypto/ripemd160"
	"log"
)

const version  = byte(0x00)
const addressChecksumLen  = 4


type Wallet struct {
	//1. 私钥
	PrivateKey ecdsa.PrivateKey

	// 2. 公钥
	PublicKey []byte
}

// 校验地址是否有效
func IsValidForAddress(address []byte) bool  {

	version_public_checksumBytes := Base58Decode(address)

	fmt.Println(version_public_checksumBytes)
	//fmt.Printf("version_public_checksumBytes:%v\n",version_public_checksumBytes)

	// 25  -  4  21
	checkSumBytes := version_public_checksumBytes[len(version_public_checksumBytes)-addressChecksumLen:]

	version_ripemd160 := version_public_checksumBytes[:len(version_public_checksumBytes)-addressChecksumLen]

	checkBytes := CheckSum(version_ripemd160)

	if bytes.Compare(checkSumBytes, checkBytes) == 0 {
		return true
	}

	return false

}

// 创建钱宝
func NewWallet() *Wallet{
	privateKey , publicKey := newKeyPair()

	//fmt.Println(privateKey)
	//fmt.Println(publicKey)

	return &Wallet{privateKey,publicKey}
}

func (w *Wallet) GetAddress() []byte  {

	// 1.hash160

	ripemd160Hash := w.Ripemd160Hash(w.PublicKey)

	version_ripemd160Hash := append([]byte{version},ripemd160Hash...)

	checkSumBytes := CheckSum(version_ripemd160Hash)

	bytes := append(version_ripemd160Hash,checkSumBytes...)

	return Base58Encode(bytes)

}

// sha256 加密2次
func CheckSum(payload []byte)[]byte  {

	hash1 := sha256.Sum256(payload)
	hash2 := sha256.Sum256(hash1[:])

	return hash2[:addressChecksumLen]
}

func (w *Wallet) Ripemd160Hash(publicKey []byte) []byte  {

	// 256

	hash256 := sha256.New()
	hash256.Write(publicKey)
	hash := hash256.Sum(nil)

	//160

	ripemd160_ := ripemd160.New()
	ripemd160_.Write(hash)

	return ripemd160_.Sum(nil)

}

// 通过私钥产生私钥
func newKeyPair() (ecdsa.PrivateKey,[]byte){

	curve := elliptic.P256()
	private , err := ecdsa.GenerateKey(curve,rand.Reader)
	if err != nil {
		log.Panic(err)
	}

	pubkey := append(private.PublicKey.X.Bytes(),private.PublicKey.Y.Bytes()...)

	return *private, pubkey

}

